// 滑动窗口
// 利用 单调性， 使用 同向双指针 的方法进行优化，使得时间复杂度降低 O(N)
// 定义 双指针 用于维护 窗口 的左右边界
// 进窗口 -> 判断是否出窗口，过程中统计结果

// 请注意，如果题目难以直接解决，要想到 “正难则反” 的解题思路
// 尤其是数组，如果要解决的问题，涉及数组的头和尾，出现不连续的情况，取中间连续的区域进行处理，往往有助于解决问题

// 例题 4：
// 给你一个整数数组 nums 和一个整数 x 。每一次操作时，你应当移除数组 nums 最左边或最右边的元素，然后从 x 中减去该元素的值。
// 请注意，需要 修改 数组以供接下来的操作使用。
// 如果可以将 x 恰好 减到 0 ，返回 最小操作数 ；否则，返回 -1 。
//
//        示例 1：
//
//        输入：nums = [1,1,4,2,3], x = 5
//        输出：2
//        解释：最佳解决方案是移除后两个元素，将 x 减到 0 。
//        示例 2：
//
//        输入：nums = [5,6,7,8,9], x = 4
//        输出：-1
//        示例 3：
//
//        输入：nums = [3,2,20,1,1,3], x = 10
//        输出：5
//        解释：最佳解决方案是移除后三个元素和前两个元素（总共 5 次操作），将 x 减到 0 。
//
//        提示：
//
//        1 <= nums.length <= 105
//        1 <= nums[i] <= 104
//        1 <= x <= 109

// 解题思路：
// 与例题 1 相同
// 进窗口：sum += nums[left]
// 当 sum > target，出窗口：sum -= nums[left] left++
// 当 sum == target，更新结果
public class minOperations {
    public int minOperations(int[] nums, int x) {
        int n = nums.length;
        int sum = 0;
        for(int num : nums) sum += num;
        int target = sum - x;
        if(target < 0) return -1;
        int left  = 0;
        int right = 0;
        sum = 0;
        int ret = -1;
        while(right < n){
            sum += nums[right];
            while(sum > target){
                sum -= nums[left];
                left++;
            }
            if(sum == target) ret = Math.max(ret, right - left + 1);
            right++;
        }
        return ret == -1 ? -1 : n - ret;
    }
}
